<?php
// +----------------------------------------------------------------------
// | XShop小程序商城
// +----------------------------------------------------------------------
// | Author: Peak Xin <xinyflove@gmail.com>
// +----------------------------------------------------------------------

namespace app\api\service;


use app\api\model\Order as OrderModel;
use app\api\model\OrderProduct as OrderProductModel;
use app\api\model\Product as ProductModel;
use app\api\model\UserAddress;
use app\lib\enum\OrderStatusEnum;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use think\Db;
use think\Exception;

class Order {

    // 订单的商品列表，也就是客户端传递过来的products参数
    protected $oProducts;
    // 真实的商品信息（包括库存量）
    protected $products;

    protected $uid;

    /**
     * 下单
     * @param $uid
     * @param $oProducts
     * @return array
     * @throws Exception
     */
    public function place($uid, $oProducts)
    {
        // oProducts和products作对比
        // products从数据库中查询出来
        $this->oProducts = $oProducts;
        $this->products = $this->__getProductsByOrder($oProducts);
        $this->uid = $uid;
        $status = $this->__getOrderStatus();
        if(!$status['pass'])
        {
            $status['order_id'] = -1;
            return $status;
        }

        // 开始创建订单
        $orderSnap = $this->__snapOrder($status);
        $order = $this->__createOrder($orderSnap);
        $order['pass'] = true;
        return $order;
    }

    /**
     * 创建订单
     * @param $snap
     * @return array
     * @throws Exception
     * @throws \Exception
     */
    private function __createOrder($snap)
    {
        Db::startTrans();
        try
        {
            $orderNo = $this->makeOrderNo();
            $orderMdl = new OrderModel();
            $orderMdl->user_id = $this->uid;
            $orderMdl->order_no = $orderNo;
            $orderMdl->total_price = $snap['orderPrice'];
            $orderMdl->total_count = $snap['totalCount'];
            $orderMdl->snap_name = $snap['snapName'];
            $orderMdl->snap_img = $snap['snapImg'];
            $orderMdl->snap_address = $snap['snapAddress'];
            $orderMdl->snap_items = json_encode($snap['pStatus']);

            $orderMdl->save();

            $orderID = $orderMdl->id;
            $create_time = $orderMdl->create_time;

            foreach ($this->oProducts as &$p)
            {
                $p['order_id'] = $orderID;
            }
            $orderProductMdl = new OrderProductModel();
            $orderProductMdl->saveAll($this->oProducts);
            Db::commit();

            return array(
                'order_no' => $orderNo,
                'order_id' => $orderID,
                'create_time' => $create_time,
            );
        }
        catch (Exception $e)
        {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 生成订单号
     * @return string
     */
    public function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y')) - 2019] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
        return $orderSn;
    }

    /**
     * 生成订单快照
     * @param $status
     * @return array
     * @throws UserException
     */
    private function __snapOrder($status)
    {
        $snap = array(
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatus' => array(),
            'snapAddress' => null,
            'snapName' => '',
            'snapImg' => '',
        );

        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this->__getUserAddress());
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];

        if(count($this->products) > 1)
        {
            $snap['snapName'] .= '等';
        }
        
        return $snap;
    }

    /**
     * 获取用户收货地址
     * @return array
     * @throws UserException
     */
    private function __getUserAddress()
    {
        $userAddress = UserAddress::where('user_id', $this->uid)->find();
        if(!$userAddress)
        {
            throw new UserException([
                'msg' => '用户收货地址不存在，下单失败',
                'errorCode' => 60001,
            ]);
        }
        return $userAddress->toArray();
    }

    /**
     * 检查订单库存
     * @param $orderID
     * @return array
     */
    public function checkOrderStock($orderID)
    {
        $oProducts = OrderProductModel::where('order_id', '=', $orderID)->select();
        $this->oProducts = $oProducts;
        
        $this->products = $this->__getProductsByOrder($oProducts);
        $status = $this->__getOrderStatus();
        return $status;
    }

    /**
     * 获取订单状态
     * @return array
     * @throws OrderException
     */
    private function __getOrderStatus()
    {
        $status = array(
            'pass' => true,
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatusArray' => array(),
        );
        
        foreach ($this->oProducts as $oProduct)
        {
            $pStatus = $this->__getProductStatus(
                $oProduct['product_id'], $oProduct['count'], $this->products
            );

            if (!$pStatus['haveStock'])
            {
                $status['pass'] = false;
            }

            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['counts'];
            array_push($status['pStatusArray'], $pStatus);
        }

        return $status;
    }

    /**
     * 获取产品状态
     * @param $oPID
     * @param $oCount
     * @param $products
     * @return array
     * @throws OrderException
     */
    private function __getProductStatus($oPID, $oCount, $products)
    {
        $pIndex = -1;
        
        $pStatus = array(
            'id' => null,
            'haveStock' => false,
            'counts' => 0,
            'price' => 0,// 商品单价
            'name' => '',
            'totalPrice' => 0,// 订单总价
            'main_img_url' => null,
        );
        
        for ($i=0; $i<count($products); $i++)
        {
            if ($oPID == $products[$i]['id'])
            {
                $pIndex = $i;
            }
        }
        
        if ($pIndex == -1)
        {
            // 客户端传递的product_id有可能根本不存在
            throw new OrderException([
                'msg' => 'id为'.$oPID.'的商品不存在，创建订单失败'
            ]);
        }

        $product = $products[$pIndex];
        $pStatus['id'] = $product['id'];
        $pStatus['name'] = $product['name'];
        $pStatus['counts'] = $oCount;
        $pStatus['price'] = $product['price'];
        $pStatus['main_img_url'] = $product['main_img_url'];
        $pStatus['totalPrice'] = $product['price'] * $oCount;
        $product['stock'] - $oCount >= 0 && $pStatus['haveStock'] = true;

        return $pStatus;
    }

    /**
     * 根据订单信息查找真实的商品信息
     * @param $oProducts
     */
    private function __getProductsByOrder($oProducts)
    {
        $oPIDs = array();

        foreach ($oProducts as $item)
        {
            array_push($oPIDs, $item['product_id']);
        }

        $products = ProductModel::all($oPIDs)
            ->visible(['id', 'price', 'stock', 'name', 'main_img_url'])
            ->toArray();

        return $products;
    }

    /**
     * 发货
     * @param $orderID
     * @param string $jumpPage
     * @return mixed
     * @throws OrderException
     */
    public function delivery($orderID, $jumpPage = '')
    {
        $order = OrderModel::where('id', '=', $orderID)
            ->find();
        if (!$order) {
            throw new OrderException();
        }
        if ($order->status != OrderStatusEnum::PAID) {
            $_msg = '你已经更新过订单了，不要再刷了';
            $order->status == OrderStatusEnum::UNPAID && $_msg = '还没付款呢，想干嘛？';
            
            throw new OrderException([
                'msg' => $_msg,
                'errorCode' => 80002,
                'code' => 403
            ]);
        }
        $order->status = OrderStatusEnum::DELIVERED;
        $order->save();
           // ->update(['status' => OrderStatusEnum::DELIVERED]);
        
        /*发送发货的微信模版消息*/
        $message = new DeliveryMessage();
        return $message->sendDeliveryMessage($order, $jumpPage);
    }
}